"""
FIVEDASH(TM) -- General Purpose Accounting Software
Copyright (C) 2008  Obol Software Pty Ltd

This program is free software: you can redistribute it and/or modify
it. For terms and conditions, see fivedash/license/license.txt

"""

import re
from phunc.utils import HTMLEncode
from phunc.logger import logger

registered_tags = {}

class NodeValueError(Exception):
        pass

class Node:
        def debugprt( self, spacessize = 0 ):
                pass
        def rander(self,content):
                pass
                    
class NodeList(list):
        def debugprt( self, spacesize = 0 ):
                strlist=[]
                for node in self:
                        if isinstance(node, Node):
                                strlist = strlist + node.debugprt( spacesize )
                        elif isinstance(node,  NodeList):
                                strlist = strlist + node.debugprt( spacesize )
                return strlist
                
        def rander(self, content):
                txtlist = []
                for node in self:
                        if isinstance(node, Node):
                                txtlist.append( node.rander( content ) )
                        else:
                                nodestr = '%s' % node
                                txtlist.append( nodestr )
                return ''.join( txtlist )

                    
class TextNode(Node):
        def debugprt( self, spacessize = 0 ):
                strlist=[]
                strlist.append('%sTextNode:  len: %s' % ( ' '*spacessize, len( self.text ) ) )
                return strlist
                
        def __init__(self, text ):
                self.text = text
                    
        def rander(self,content):
                nodestr = '%s' % self.text
                return nodestr
            
class VarNode(Node):
        def debugprt( self, spacessize = 0 ):
                strlist=[]
                strlist.append('%sVarNode:  name: %s' % ( ' '*spacessize, self.varname ) )
                return strlist

        def __init__(self, varname ):
                self.varname = varname
                
        def rander(self, content):
##                dictpattern = re.compile(r'''(.*)\['(.*)'\]''')
##                sresult = dictpattern.search( self.varname )
##                if sresult != None and len(sresult.groups()) == 2:
##                        dictname = sresult.groups()[0]
##                        dictindex = sresult.groups()[1]
##                        varvalue =  content[dictname][dictindex]
##                else:
##                        varvalue = content[self.varname]
##                for var_key in self.varname:
##                        if var_key not in content.keys():
##                                logger.debug("Content have no key: '%s'" %  var_key)
##                varvalue = None
                flag = 0
                for ct in content.keys():
                        if ct in self.varname:
                                flag = 1
                                break
                if flag==0:
                        logger.debug("Content have no key: '%s'" %  self.varname)
                for ct in content.keys():
                        if ct in self.varname:
                                locals()[ct] = content[ct]
                varvalue = eval( self.varname )
                #if varvalue == None:
                        #logger.debug("Content have no value(s): '%s'" %  self.varname) 
                #NodeValueError, "Content have no value(s): '%s'" %  self.varname
                # if the varvalue is None ,don't throw out exception
                if varvalue == None:
                        varvalue = ''
                nodestr = '%s' % varvalue
                return nodestr
                    
class TranslateNode(Node):
        def debugprt( self, spacessize = 0 ):
                strlist=[]
                strlist.append('%sTranslateNode:  len: %s' % ( ' '*spacessize, len( self.text ) ) )
                return strlist

        def __init__(self, text ):
                self.text = text
                    
        def rander(self,content):
                #to_do call the  translate func
                nodestr = '%s' % self.text
                return nodestr

                    
class IfNode(Node):
        def debugprt( self, spacessize = 0 ):
                strlist=[]
                strlist.append('%sIfNode:  cond: %s' % ( ' '*spacessize,  self.cond ) )
                strlist.append('%s         true_list:' % (' '*spacessize) )
                strlist  = strlist + self.true_list.debugprt( spacessize + 16 )
                strlist.append('%s         false_list:' % (' '*spacessize) )
                strlist = strlist + self.false_list.debugprt( spacessize + 16 )
                return strlist

        def __init__(self, cond, true_list, false_list ):
                self.cond,self.true_list,self.false_list = cond,true_list,false_list
                
        def rander(self,content):
                #input all content in locals()
                for name in content.keys():
                        locals()[name] = content[name]
                if eval( self.cond ):
                        return  self.true_list.rander( content )
                else:
                        return self.false_list.rander( content )
                    

class ForNode(Node):
		def debugprt( self, spacessize = 0 ):
				strlist=[]
				strlist.append('%sForNode: var: %s seq: %s' % ( ' '*spacessize, self.loopvar ,self.seq  ) )
				strlist.append('%s         for_list:' % (' '*spacessize) )
				strlist = strlist + self.slist.debugprt( spacessize + 16 )
				return strlist
		
		def __init__(self, loopvar, seq , slist):
				self.loopvar,self.seq,self.slist = loopvar,seq,slist
				
		def rander(self,content):
				node_list = NodeList()
				v=[]
				vv=[]
				if self.seq.strip().find('.')>=0:
						elements = self.seq.strip().split('.')
						if elements[0].find('[') >=0:
							key =re.search("\\[.*\\]",elements[0]).group()
							key_elements=elements[0].split('[')
							seq_list=content[key_elements[0]][key[1:-1][1:-1]]							
							if elements[1].find('()')>=0:							
								if hasattr(seq_list,elements[1][:elements[1].rindex('()')]):								
									seq_list = getattr(seq_list,elements[1][:elements[1].rindex('()')])()
						else:
							seq_list = content[elements[0]][elements[1]]
				elif self.seq.strip().find('zip')>=0:
					elem =re.search("\\(.*\\)",self.seq.strip()).group()[1:-1]
					for i in range(len(self.seq.strip().split(','))):
						if self.seq.strip().find('[') <0:
							locals()["x"+str(i)] =content[elem.split(',')[i]]
						else:
							locals()["elem"+str(i)]=elem.split(',')[i].split('[')
							locals()["key"+str(i)] =re.search("\\[.*\\]",elem.split(',')[i]).group()
							locals()["x"+str(i)]=content[locals()["elem"+str(i)][0]][locals()["key"+str(i)][2:-2]]
						locals()["a"+str(i)]=[]
						v.append(locals()["a"+str(i)])
						vv.append(locals()["x"+str(i)])
				elif self.seq.strip().find('[') >=0:
						key =re.search("\\[.*\\]",self.seq.strip()).group()
						elements=self.seq.strip().split('[')
						seq_list=content[elements[0]][key[1:-1][1:-1]]
				else:                        
						seq_list = content[ self.seq ]
						
				if self.seq.strip().find('zip')>=0:
					for v in zip(*vv):
						for i in range(len(self.seq.strip().split(','))):
							content[self.loopvar.split(',')[i]]=v[i]
						for s in self.slist:
							node_list.append(s.rander(content))
				else:
					for seq in seq_list:
							content[ self.loopvar ] = seq
							for s in self.slist:
									node_list.append( s.rander( content ) )
				return node_list.rander( content )

                    
# --------------------------------------------------------------------------------------------------------------------------------------------
# do_command                     
def do_if( parse, curr_token ):
        elements = curr_token.value.strip().split('if')
        var = elements[1]
        true_list = parse.process( ['else','endif'] )
        next_token = parse.next_token()
        false_list = NodeList()
        if next_token.value.strip() == 'else':
                false_list = parse.process( ['endif'] )
                parse.next_token()
        return IfNode( var, true_list, false_list )

            
def do_for( parse, curr_token ):
        elements = curr_token.value.strip().split()
        loopvar = elements[1]
        sequence = elements[3]
        nodelist_loop = parse.process( ['endfor'] )
        parse.next_token()
        return ForNode( loopvar, sequence, nodelist_loop )


#regist the command
registered_tags['if'] = do_if
registered_tags['for'] = do_for
